// 导入必要的Java包
import javax.script.ScriptEngine;          // 1. 用于执行数学表达式的脚本引擎接口
import javax.script.ScriptEngineManager;    // 2. 管理脚本引擎的工厂类
import javax.script.ScriptException;        // 3. 脚本执行异常的基类
import javax.swing.*;                       // 4. Swing GUI组件包(按钮、面板等)
import javax.swing.border.EmptyBorder;      // 5. 创建空边框的类
import java.awt.*;                          // 6. AWT图形组件包(布局、颜色等)
import java.awt.event.ActionEvent;          // 7. 按钮点击事件类
import java.awt.event.ActionListener;       // 8. 按钮事件监听器接口
import java.io.File;                        // 9. 文件操作类
import javax.sound.sampled.*;               // 10. 音频处理相关类

// 计算器主类
public class Calculator extends JFrame implements ActionListener { // 11. 继承JFrame并实现事件监听
    // 界面组件声明
    private JPanel north, center;           // 12. 上方和中央面板组件
    private JTextField field;               // 13. 结果显示文本框
    private JButton[] btns;                 // 14. 按钮数组(所有计算器按钮)
    private ScriptEngine engine;            // 15. JavaScript计算引擎
    private Clip buttonClickSound;          // 16. 按钮点击音效剪辑对象
    
    /*========== 紫色主题配色方案 ==========*/
    private Color bgColor = new Color(48, 48, 96);         // 17. 深紫色背景
    private Color buttonColor = new Color(147, 112, 219);  // 18. 紫色数字按钮
    private Color operatorColor = new Color(255, 215, 0);  // 19. 金色运算符按钮
    private Color specialColor = new Color(186, 85, 211);  // 20. 紫罗兰特殊按钮
    private Color textColor = Color.WHITE;                  // 21. 白色文字
    private Color fieldBgColor = new Color(30, 30, 60);     // 22. 深色文本框背景

    // 构造函数
    public Calculator() {
        setTitle("紫色主题计算器(带阶乘功能)");  // 23. 设置窗口标题
        setSize(700, 700);                 // 24. 设置窗口尺寸700x700像素
        setDefaultCloseOperation(EXIT_ON_CLOSE); // 25. 关闭窗口时退出程序
        setLocationRelativeTo(null);        // 26. 窗口居中显示
        
        initComponent();    // 27. 调用初始化组件方法
        loadButtonSound();  // 28. 调用加载音效方法
        setVisible(true);   // 29. 显示窗口
    }

    // 加载按钮点击音效方法
    private void loadButtonSound() {
        try {
            // 音效文件路径
            String soundPath = "C:\\Users\\lenovo\\Desktop\\新建文件夹\\6月28日 (1)\\6月28日 (1).WAV"; // 30. 音效文件路径
            File soundFile = new File(soundPath); // 31. 创建文件对象
            
            if (soundFile.exists()) { // 32. 检查文件是否存在
                // 创建音频输入流
                AudioInputStream audioInput = AudioSystem.getAudioInputStream(soundFile); // 33. 获取音频输入流
                // 获取音频剪辑
                buttonClickSound = AudioSystem.getClip(); // 34. 获取Clip实例
                // 打开音频流
                buttonClickSound.open(audioInput); // 35. 打开音频流
                
                // 设置音量控制
                FloatControl gainControl = (FloatControl) buttonClickSound.getControl(FloatControl.Type.MASTER_GAIN); // 36. 获取音量控制
                gainControl.setValue(-10.0f); // 37. 设置音量降低10分贝
            } else {
                // 文件不存在时的处理
                System.out.println("按钮音效文件未找到: " + soundPath); // 38. 控制台输出错误
                JOptionPane.showMessageDialog(this, 
                    "未找到按钮音效文件: " + soundPath, 
                    "音效文件错误", 
                    JOptionPane.WARNING_MESSAGE); // 39. 显示警告对话框
            }
        } catch (Exception e) {
            // 异常处理
            e.printStackTrace(); // 40. 打印异常堆栈
            System.out.println("加载按钮音效时出错"); // 41. 控制台输出错误
            JOptionPane.showMessageDialog(this, 
                "加载按钮音效时出错: " + e.getMessage(), 
                "音效错误", 
                JOptionPane.ERROR_MESSAGE); // 42. 显示错误对话框
        }
    }

    // 播放音效方法
    private void playButtonSound() {
        if (buttonClickSound != null) { // 43. 检查音效是否加载
            buttonClickSound.setFramePosition(0); // 44. 重置播放位置到开头
            buttonClickSound.start();             // 45. 开始播放音效
        } else {
            Toolkit.getDefaultToolkit().beep();   // 46. 备用系统提示音
        }
    }

    // 初始化界面组件方法
    private void initComponent() {
        // 创建面板
        north = new JPanel();  // 47. 创建上方显示面板
        center = new JPanel(); // 48. 创建中央按钮面板
        
        // 设置面板背景色
        north.setBackground(bgColor); // 49. 设置北面板背景色
        center.setBackground(bgColor); // 50. 设置中央面板背景色
        getContentPane().setBackground(bgColor); // 51. 设置内容面板背景色
        
        /*----- 文本框配置 -----*/
        field = new JTextField(); // 52. 创建文本框
        field.setPreferredSize(new Dimension(700, 150)); // 53. 设置文本框大小
        field.setEditable(false);  // 54. 禁止直接编辑
        field.setFont(new Font("Segoe UI", Font.BOLD, 35)); // 55. 设置字体样式
        field.setHorizontalAlignment(JTextField.RIGHT); // 56. 文本右对齐
        field.setBorder(new EmptyBorder(10, 10, 10, 10)); // 57. 设置内边距
        field.setBackground(fieldBgColor); // 58. 文本框背景色
        field.setForeground(textColor);    // 59. 文本框文字颜色
        
        // 初始化JavaScript引擎
        engine = new ScriptEngineManager().getEngineByName("JavaScript"); // 60. 创建JS引擎实例

        /*----- 按钮定义 -----*/
        String[] btnLabels = new String[]{ // 61. 定义按钮标签数组
            "7", "8", "9", "+",     // 62. 第一行按钮
            "4", "5", "6", "-",     // 63. 第二行
            "1", "2", "3", "×",     // 64. 第三行
            "0", ".", "=", "÷",     // 65. 第四行
            "C", "B", "√", "!"      // 66. 第五行功能键
        };
        
        // 初始化按钮数组
        btns = new JButton[btnLabels.length]; // 67. 创建按钮数组
        for (int i = 0; i < btns.length; i++) { // 68. 遍历按钮标签
            btns[i] = new JButton(btnLabels[i]); // 69. 创建按钮实例
            
            // 设置按钮样式
            btns[i].setFont(new Font("Segoe UI", Font.BOLD, 35)); // 70. 设置按钮字体
            btns[i].setFocusPainted(false);  // 71. 取消焦点边框
            btns[i].setForeground(textColor); // 72. 设置文字颜色
            
            // 根据按钮类型设置不同颜色
            if (btnLabels[i].matches("[0-9.]")) { // 73. 数字和小数点按钮
                btns[i].setBackground(buttonColor); 
            } 
            else if (btnLabels[i].matches("[+\\-×÷=]")) { // 74. 运算符按钮
                btns[i].setBackground(operatorColor); 
            } 
            else if (btnLabels[i].matches("[!√]")) { // 75. 特殊功能按钮
                btns[i].setBackground(new Color(255, 165, 0)); // 橙色
            }
            else { // 76. 其他功能按钮
                btns[i].setBackground(specialColor); 
            }
            
            // 鼠标悬停效果
            btns[i].addMouseListener(new java.awt.event.MouseAdapter() { // 77. 添加鼠标监听器
                public void mouseEntered(java.awt.event.MouseEvent evt) { // 78. 鼠标进入事件
                    JButton button = (JButton)evt.getSource();
                    // 鼠标移入时变亮
                    button.setBackground(new Color( // 79. 计算更亮的颜色
                        Math.min(button.getBackground().getRed() + 30, 255),
                        Math.min(button.getBackground().getGreen() + 30, 255),
                        Math.min(button.getBackground().getBlue() + 30, 255)
                    ));
                }
                public void mouseExited(java.awt.event.MouseEvent evt) { // 80. 鼠标离开事件
                    // 鼠标移出时恢复原色
                    JButton button = (JButton)evt.getSource();
                    if (button.getText().matches("[0-9.]")) { // 81. 数字按钮恢复
                        button.setBackground(buttonColor);
                    } else if (button.getText().matches("[+\\-×÷=]")) { // 82. 运算符恢复
                        button.setBackground(operatorColor);
                    } else if (button.getText().matches("[!√]")) { // 83. 特殊功能恢复
                        button.setBackground(new Color(255, 165, 0));
                    } else { // 84. 其他按钮恢复
                        button.setBackground(specialColor);
                    }
                }
            });
        }

        /*----- 布局管理 -----*/
        north.setLayout(new BorderLayout());  // 85. 上方面板使用边界布局
        center.setLayout(new GridLayout(5, 4, 10, 10)); // 86. 中央面板5行4列网格布局
        center.setBorder(new EmptyBorder(10, 10, 10, 10)); // 87. 设置内边距
        
        // 添加组件
        north.add(field, BorderLayout.CENTER); // 88. 文本框添加到北面板中央
        for (JButton btn : btns) { // 89. 遍历所有按钮
            center.add(btn); // 90. 将按钮添加到中央面板
        }
        
        // 主窗口布局
        add(north, BorderLayout.NORTH);  // 91. 北面板添加到窗口顶部
        add(center);                    // 92. 中央面板添加到窗口中心

        // 为所有按钮添加事件监听
        for (JButton btn : btns) { // 93. 遍历所有按钮
            btn.addActionListener(this); // 94. 添加动作监听器
        }
    }

    // 计算阶乘的辅助方法
    private long calculateFactorial(int n) { // 95. 阶乘计算方法
        if (n < 0) return -1; // 96. 负数无阶乘
        if (n > 20) return -2; // 97. 超过20会超出long的范围
        
        long result = 1; // 98. 初始化结果为1
        // 计算阶乘
        for (int i = 2; i <= n; i++) { // 99. 循环计算阶乘
            result *= i; // 100. 累乘
        }
        return result; // 101. 返回结果
    }

    // 处理按钮点击文本输入
    private void setBtnText(String text) { // 102. 处理按钮点击逻辑
        String currentText = field.getText(); // 103. 获取当前文本框内容
        String lastChar = currentText.isEmpty() ? "" : currentText.substring(currentText.length() - 1); // 104. 获取最后一个字符
        
        // 根据按钮类型处理
        switch (text) { // 105. 根据按钮文本切换
            case "C":  // 清除
                field.setText(""); // 106. 清空文本框
                break;
                
            case "B":  // 退格
                if (!currentText.isEmpty()) { // 107. 非空时处理
                    field.setText(currentText.substring(0, currentText.length() - 1)); // 108. 删除最后一个字符
                }
                break;
                
            case "√":  // 平方根
                if (!currentText.isEmpty()) { // 109. 非空时处理
                    try {
                        double num = Double.parseDouble(currentText); // 110. 转换为double
                        field.setText(num >= 0 ? formatResult(Math.sqrt(num)) : "错误"); // 111. 计算平方根或显示错误
                    } catch (NumberFormatException e) {
                        field.setText("错误"); // 112. 数字格式异常
                    }
                }
                break;
                
            case "!":  // 阶乘运算
                if (!currentText.isEmpty() && !lastChar.matches("[+\\-×÷!]")) { // 113. 非空且不以运算符结尾
                    try {
                        int num = Integer.parseInt(currentText); // 114. 转换为整数
                        long factorial = calculateFactorial(num); // 115. 计算阶乘
                        
                        if (factorial == -1) { // 116. 负数情况
                            field.setText("负数无阶乘");
                        } else if (factorial == -2) { // 117. 过大数字
                            field.setText("超过20!");
                        } else {
                            field.setText(String.valueOf(factorial)); // 118. 显示结果
                        }
                    } catch (NumberFormatException e) {
                        field.setText("错误"); // 119. 数字格式异常
                    }
                }
                break;
                
            case "=":  // 计算结果
                if (!currentText.isEmpty() && !lastChar.matches("[+\\-×÷.]")) { // 120. 非空且不以运算符或小数点结尾
                    try {
                        // 转换符号为JavaScript可识别的运算符
                        String expression = currentText.replace("×", "*") // 121. 替换乘号
                                                     .replace("÷", "/") // 122. 替换除号
                                                     .replace(" ", ""); // 123. 去除空格
                        Object result = engine.eval(expression); // 124. 执行表达式
                        field.setText(formatResult(result)); // 125. 格式化并显示结果
                    } catch (ScriptException e) {
                        field.setText("错误"); // 126. 脚本执行错误
                    }
                }
                break;
                
            case ".":  // 小数点
                if (currentText.isEmpty()) { // 127. 空文本框时
                    field.setText("0."); // 128. 补零
                } else if (lastChar.matches("[+\\-×÷]")) { // 129. 运算符后
                    field.setText(currentText + "0."); // 130. 补零加点
                } else {
                    String[] parts = currentText.split("[+\\-×÷]"); // 131. 分割表达式
                    if (!parts[parts.length-1].contains(".")) { // 132. 当前数字不含小数点
                        field.setText(currentText + "."); // 133. 添加小数点
                    }
                }
                break;
                
            case "+": case "-": case "×": case "÷":  // 运算符
                if (!currentText.isEmpty() && !lastChar.matches("[+\\-×÷.]")) { // 134. 非空且不以运算符或小数点结尾
                    field.setText(currentText + text); // 135. 添加运算符
                } else if (text.equals("-") && (currentText.isEmpty() || lastChar.matches("[×÷]"))) { // 136. 负号特殊情况
                    field.setText(currentText + text); // 137. 允许负号
                }
                break;
                
            default:  // 数字按钮
                field.setText(currentText + text); // 138. 直接追加数字
        }
    }

    // 格式化结果（去除多余的.0）
    private String formatResult(Object result) { // 139. 结果格式化方法
        String str = result.toString(); // 140. 转换为字符串
        if (str.endsWith(".0")) { // 141. 检查是否以.0结尾
            return str.substring(0, str.length() - 2); // 142. 去除.0
        }
        return str; // 143. 返回原字符串
    }

    // 按钮点击事件处理
    @Override
    public void actionPerformed(ActionEvent e) { // 144. 实现ActionListener接口
        if (e.getSource() instanceof JButton) { // 145. 检查事件源是否为按钮
            JButton btn = (JButton) e.getSource(); // 146. 转换为按钮对象
            
            playButtonSound();  // 147. 播放点击音效
            
            // 按钮按下动画效果
            Timer timer = new Timer(100, new ActionListener() { // 148. 创建100ms定时器
                @Override
                public void actionPerformed(ActionEvent e) {
                    // 恢复按钮颜色
                    if (btn.getText().matches("[0-9.]")) { // 149. 数字按钮恢复
                        btn.setBackground(buttonColor);
                    } else if (btn.getText().matches("[+\\-×÷=]")) { // 150. 运算符恢复
                        btn.setBackground(operatorColor);
                    } else if (btn.getText().matches("[!√]")) { // 151. 特殊功能恢复
                        btn.setBackground(new Color(255, 165, 0));
                    } else { // 152. 其他按钮恢复
                        btn.setBackground(specialColor);
                    }
                    ((Timer)e.getSource()).stop(); // 153. 停止定时器
                }
            });
            btn.setBackground(btn.getBackground().darker()); // 154. 按钮按下时变暗
            timer.start(); // 155. 启动定时器
            
            setBtnText(btn.getText());  // 156. 处理按钮逻辑
        }
    }

    // 窗口关闭时释放资源
    @Override
    public void dispose() { // 157. 重写dispose方法
        if (buttonClickSound != null) { // 158. 检查音效对象
            buttonClickSound.stop(); // 159. 停止播放
            buttonClickSound.close(); // 160. 释放资源
        }
        super.dispose(); // 161. 调用父类方法
    }

    // 程序入口
    public static void main(String[] args) { // 162. 主方法
        SwingUtilities.invokeLater(() -> { // 163. 在事件调度线程中执行
            try {
                // 设置系统外观
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // 164. 设置系统原生外观
            } catch (Exception e) {
                e.printStackTrace(); // 165. 打印异常
            }
            new Calculator(); // 166. 创建计算器实例
        });
    }
}